local BattleUtil = {}
Battle.BattleUtil = BattleUtil
local this = BattleUtil
local tempVec3 = Vector3.New()
--敌对阵营
function BattleUtil.GetEnemyCamp(campType)
    if campType == Battle.CampType.Blue then
        return Battle.CampType.Red
    end
    return Battle.CampType.Blue
end
function BattleUtil.CheckCondition(value1,compareType,value2)
    if compareType == Battle.CompareType.Equals then
        return value1 == value2
    elseif compareType == Battle.CompareType.Greater then
        return value1 > value2
    elseif compareType == Battle.CompareType.Less then
        return value1 < value2
    elseif compareType == Battle.CompareType.GreaterEquals then
        return value1 >= value2
    elseif compareType == Battle.CompareType.LessEquals then
        return value1 <= value2
    else
        return value1 ~= value2
    end
end

---两圆是否相交或内部
function BattleUtil.IsCircleIntersection(point1,radius1,point2,radius2)
    local x = point1.x - point2.x
    local z = point1.z - point2.z
    local r = radius1+radius2
    return x*x+z*z < r*r
end
---点是否在圆内
function BattleUtil.IsPointInCircle(point,circlePoint,radius)
    local x = point.x - circlePoint.x
    local z = point.z - circlePoint.z
    return x*x+z*z < radius * radius
end
function BattleUtil.IsPointInRect(pointX,pointY,topLeftX,topLeftY,bottomRightX,bottomRightY)
    return pointX >= topLeftX and pointX <= bottomRightX and pointY <= topLeftY and pointY >= bottomRightY
end
function BattleUtil.GetRandomPosInRect(lbx,lby,rtx,rty)
    local x = math.random(lbx,rtx)
    local y = math.random(lby,rty)
    return x,y
end
---矩形是否和圆相交
function BattleUtil.IsCircleIntersectionRect(rectCenterPoint,width,height,circlePoint,radius)
    local w = width/2
    local h = height/2
    local leftEdge = rectCenterPoint.x - w
    local topEdge = rectCenterPoint.z + h
    local rightEdge = rectCenterPoint.x + w
    local bottomEdge = rectCenterPoint.z - h
    --4个点
    tempVec3:Set(leftEdge,rectCenterPoint.y,bottomEdge)
    local flag = this.IsPointInCircle(tempVec3,circlePoint,radius)
    if flag then return true end
    tempVec3:Set(rightEdge,rectCenterPoint.y,bottomEdge)
    flag = this.IsPointInCircle(tempVec3,circlePoint,radius)
    if flag then return true end
    tempVec3:Set(rightEdge,rectCenterPoint.y,topEdge)
    flag = this.IsPointInCircle(tempVec3,circlePoint,radius)
    if flag then return true end
    tempVec3:Set(leftEdge,rectCenterPoint.y,topEdge)
    flag = this.IsPointInCircle(tempVec3,circlePoint,radius)
    if flag then return true end
    --圆心
    flag = this.IsPointInRect(circlePoint.x,circlePoint.z,leftEdge,topEdge,rightEdge,bottomEdge)
    if flag then return true end
    --边
    flag = (leftEdge - circlePoint.x) <= radius and circlePoint.z < topEdge and circlePoint.z > bottomEdge
    if flag then return true end
    flag = (rightEdge - circlePoint.x) <= radius and circlePoint.z < topEdge and circlePoint.z > bottomEdge
    if flag then return true end
    flag = (topEdge - circlePoint.z) <= radius and circlePoint.x < rightEdge and circlePoint.x > leftEdge
    if flag then return true end
    flag = (bottomEdge - circlePoint.z) <= radius and circlePoint.x < rightEdge and circlePoint.x > leftEdge
    if flag then return true end
    return flag
end

function BattleUtil.DistanceSqr(pos1,pos2)
    local x = pos1.x - pos2.x
    local z = pos1.z - pos2.z
    return x*x+z*z
end
function BattleUtil.Distance(pos1,pos2)
    local x = pos1.x - pos2.x
    local z = pos1.z - pos2.z
    return math.sqrt(x*x+z*z)
end
---@class Battle.ConditionData
local conditionData = {}
function BattleUtil.CreateConditionData(target)
    ---@type Battle.Entity
    conditionData.target = target
    return conditionData
end

---@class Battle.DamageData
local damageData = {}
---@param attacker Battle.Entity
---@param target Battle.Entity
function BattleUtil.CreateDamageData(attacker,target,hurtType,damage,isCrit,sourceType,sourceId)
    return this.CreateDamageData2(damageData,attacker,target,hurtType,damage,isCrit,sourceType,sourceId)
end
---@param tb Battle.DamageData
---@param attacker Battle.Entity
---@param target Battle.Entity
function BattleUtil.CreateDamageData2(tb,attacker,target,hurtType,damage,isCrit,sourceType,sourceId,isTransferDamage)
    ---@type Battle.Entity
    tb.attacker = attacker
    ---@type Battle.Entity
    tb.target = target
    tb.hurtType = hurtType
    tb.damage = damage
    tb.isCrit = isCrit
    tb.sourceType = sourceType
    tb.sourceId = sourceId
    tb.isTransferDamage = isTransferDamage
    return tb
end
---最终伤害
---@param attacker Battle.Entity
---@param defender Battle.Entity
function BattleUtil.CalcRealDamage(damage,hurtType,attacker,defender,sourceType,sourceId)
    local per = 1
    if attacker.atkType == Battle.AttackAttrType.accurate then
        per = 100/(100+defender.attrSystem:GetAttr(Battle.AttributeType.Accurate_Resist))
    elseif attacker.atkType == Battle.AttackAttrType.Penetration then
        per = 100/(100+defender.attrSystem:GetAttr(Battle.AttributeType.Penetrate_Resist))
    end
    local realDamage = damage
    if hurtType == Battle.HurtType.Common then
        realDamage = math.max(0,damage - defender.attrSystem:GetDef()) * per
    elseif hurtType == Battle.HurtType.Holy then
        realDamage = damage*per
    elseif hurtType == Battle.HurtType.Treat then
        realDamage = -damage
    end
    local isCrit = false
    local crit_rate = attacker.attrSystem:GetAttr(Battle.AttributeType.CRIT_RATE)
    if crit_rate > 0 then
        local r = math.random(0,10000)
        if r <= crit_rate then
            isCrit = true
            realDamage = realDamage * (attacker.attrSystem:GetAttr(Battle.AttributeType.CRIT)/10000)
        end
    end
    return this.CreateDamageData(attacker,defender,hurtType,realDamage,isCrit,sourceType,sourceId)
end
---攻击间隔
---@param actor Battle.Entity
function BattleUtil.CalcAttackDuring(actor)
    --基础攻速
    local base = actor.attrSystem:GetBaseAttr(Battle.AttributeType.ATK_RATE)
    --基础攻击间隔
    local during = DataTable.GetById("t_skill",actor.skillSystem:GetNormalSkillId(),"f_SkillDuration")
    during = during/1000
    --实际攻速
    local speed = base
    for k,v in ipairs(actor.attrSystem.atkRateList) do
        if v > 0 then
            speed = math.min(speed/100*(100+v/100),600)
        end
    end
    --实际攻击间隔
    during = (100*during)/speed
    during = math.max(during,0.33)
    --技能buff附加的额外减攻速
    --实际攻击间隔
    for k,v in ipairs(actor.attrSystem.atkRateList) do
        if v < 0 then
            during =  during*(1+v/10000)
        end
    end
    return during
end
---移动速度
---@param actor Battle.Entity
function BattleUtil.CalcSpeed(actor)
    --基础移速
    local base = actor.attrSystem:GetBaseAttr(Battle.AttributeType.SPEED)
    --实际移速(加)
    local speed =  base
    for k,v in ipairs(actor.attrSystem.atkRateList) do
        if v > 0 then
            speed = speed *(1+v)
        end
    end
    --实际移速(减)
    for k,v in ipairs(actor.attrSystem.atkRateList) do
        if v < 0 then
            speed = speed *(1+v)
        end
    end
    return speed
end
